from __future__ import with_statement
import csv
from urllib2 import quote
from rdflib_tools.describer import Describer
from rdflib.graph import Graph, ConjunctiveGraph
from rdflib.namespace import Namespace, RDF, RDFS, OWL, _XSD_NS as XSD
from rdflib.term import BNode, Identifier, Literal, URIRef, Variable


def make_slug(s):
    return quote(s.lower().replace(" ", "_").replace(",", ""))

class Resource(object):
    def __init__(self, dataset):
        self.dataset = dataset
    @property
    def uri(self):
        return "%s/%s" % (self.dataset, self) # TODO: design, complete and adapt

class Dimension(Resource):
    def __init__(self, dataset, label):
        Resource.__init__(self, dataset)
        self.label = label
    def __str__(self):
        return make_slug(self.label)

class Region(Resource):
    def __init__(self, dataset, name):
        Resource.__init__(self, dataset)
        self.name = name
        self.items = []
    def __str__(self):
        return make_slug(self.name)

class Item(Resource):
    def __init__(self, dataset, region, dimension, year, value):
        Resource.__init__(self, dataset)
        self.region = region
        self.dimension = dimension
        self.year = year
        self.value = value
    def __str__(self):
        return "%s/by/%s/year/%s" % (self.region, self.dimension, self.year)


def make_dataset(f):
    # TODO: partition into expected "units of delivery"; e.g. all by year?
    dataset = "http://data.opengov.se/sadev.scb.se/bilateralt"
    dimension_map = {}
    regions = []
    years = None
    current_region = None
    for row in csv.reader(f):
        # when row of years is given, start compiling dataset
        if not years:
            if not any(row[0:2]) and all(col.isdigit() for col in row[2:]):
                years = [int(col) for col in row[2:]]
            else:
                # all before years are comments, not data
                pass
            continue
        if not all(row[1:]):
            continue # seems to be comment rows (at end of the spreadsheet)
        if row[0]:
            current_region = Region(dataset, row[0])
            regions.append(current_region)
        dimension = Dimension(dataset, row[1])
        dimension = dimension_map.setdefault(dimension.uri, dimension)
        for year, value in zip(years, row[2:]):
            current_region.items.append(Item(dataset, current_region, dimension, year, value))
    return dataset, dimension_map.values(), regions


FOAF = Namespace("http://xmlns.com/foaf/0.1/")
VOID = Namespace("http://rdfs.org/ns/void#")
SCOVO = Namespace("http://purl.org/NET/scovo#")
TL = Namespace("http://purl.org/NET/c4dm/timeline.owl#")

def new_describer(graph=None):
    graph = graph or Graph()
    graph.bind('xsd', XSD)
    graph.bind('void', VOID)
    graph.bind('scv', SCOVO)
    graph.bind('tl', TL)
    return Describer(graph)

def to_graph(dataset, dimensions, regions):
    d = new_describer()

    d.about(dataset)
    d.rdftype(SCOVO.Dataset)

    for dimension in dimensions:
        d.about(dimension.uri)
        d.rdftype(SCOVO.Dimension)
        d.value(RDFS.label, dimension.label, lang='en')

    for region in regions:
        d.about(region.uri)
        # TODO: Region subclass Dimension?
        d.rdftype(SCOVO.Dimension)
        d.value(RDFS.label, region.name, lang='en')
        for item in region.items:
            # TODO: subject of measurment (region) as just dimension?
            with d.rev(SCOVO.dimension, item.uri):
                d.rdftype(SCOVO.Item)
                d.rel(SCOVO.dimension, item.dimension.uri)
                d.rel(SCOVO.dataset, item.dataset)
                d.value(TL.atYear, item.year, datatype=XSD.gYear)
                d.value(RDF.value, int(item.value))
    return d.graph


if __name__ == '__main__':
    from sys import argv
    script, args = argv[0], argv[1:]
    fpath = args.pop(0)
    debug =  "-d" in args
    with open(fpath) as f:
        dataset, dimensions, regions = make_dataset(f)
        if debug:
            for region in regions:
                for item in region.items:
                    print "<%s>: %s" % (item.uri, item.value)
                print
        else:
            print to_graph(dataset, dimensions, regions).serialize(format='n3')

